package com.je.gateway.router.dispatcher;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import io.vertx.core.Vertx;
import io.vertx.core.http.Cookie;
import io.vertx.ext.web.RoutingContext;
import org.apache.servicecomb.common.rest.RestConst;
import org.apache.servicecomb.core.invocation.InvocationFactory;
import org.apache.servicecomb.core.provider.consumer.ReactiveResponseExecutor;
import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
import org.apache.servicecomb.edge.core.EdgeInvocation;
import org.apache.servicecomb.serviceregistry.RegistryUtils;
import org.apache.servicecomb.swagger.invocation.Response;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public abstract class GatewayAbstractRestDispatcher extends AbstractEdgeDispatcher {

    public static final String X_COOKIE_KEY = "x-cookie-key";

    public static final String SERVICE_INSTANCE = "x-service-instance";

    protected EdgeInvocation createEdgeInvocation(RoutingContext context) {
        return new EdgeInvocation() {
            @Override
            protected void sendResponse(Response response) {
                if (response.getHeaders(X_COOKIE_KEY) != null && !response.getHeaders(X_COOKIE_KEY).isEmpty()) {
                    Set<String> cookieHeaders = cookieHeaders(response.getHeaders(X_COOKIE_KEY));
                    for (String eachKey : cookieHeaders) {
                        Cookie cookie = Cookie.cookie(eachKey, response.getHeader(eachKey));
                        cookie.setPath("/");
                        cookie.setSecure(false);
                        context.addCookie(cookie);
                    }
                }
                super.sendResponse(response);
            }

            @Override
            protected void createInvocation() {
                ReferenceConfig referenceConfig = microserviceReferenceConfig
                        .createReferenceConfig(restOperationMeta.getOperationMeta());

                this.invocation = InvocationFactory.forConsumer(referenceConfig,
                        restOperationMeta.getOperationMeta(),
                        restOperationMeta.getOperationMeta().buildBaseConsumerRuntimeType(),
                        null);
                this.invocation.setSync(false);
                this.invocation.setEdge(true);
                //指定实例id
                this.invocation.getContext().put(SERVICE_INSTANCE, context.request().getHeader(SERVICE_INSTANCE));
                this.invocation.getHandlerContext().put(EDGE_INVOCATION_CONTEXT, Vertx.currentContext());
                this.invocation.setResponseExecutor(new ReactiveResponseExecutor());
                this.routingContext.put(RestConst.REST_INVOCATION_CONTEXT, invocation);
            }
        };
    }

    private Set<String> cookieHeaders(List<String> orginalHeaders) {
        Set<String> newHeaders = new HashSet<>();
        orginalHeaders.forEach(each -> {
            newHeaders.addAll(Splitter.on(",").splitToList(each));
        });
        return newHeaders;
    }

    protected Boolean isGateWayPath(RoutingContext context, String path) {
        if (path.indexOf("/je/gateway") >= 0 && Strings.isNullOrEmpty(context.request().getHeader(SERVICE_INSTANCE))) {
            return true;
        }
        if (!Strings.isNullOrEmpty(context.request().getHeader(SERVICE_INSTANCE)) &&
                context.request().getHeader(SERVICE_INSTANCE).equals(RegistryUtils.getMicroserviceInstance().getInstanceId())) {
            return true;
        }
        return false;
    }

}
